package com.panopset;

import java.io.StringWriter;
import java.util.Collection;
import java.util.Map;
import java.util.Map.Entry;

import com.panopset.compat.Strings;

/**
 * Objects are dumped in to the toString method.
 *
 * @author Karl Dinwiddie
 *
 */
public final class Dump {

    /**
     *
     * @param object
     *            Object to dump.
     */
    public Dump(final Object object) {
        obj = object;
    }

    /**
     * Generic dump. Collections and dumps are nicely formatted.
     *
     * @param o
     *            Object to be given a clean dump for.
     * @return String representation of given Object.
     */
    @SuppressWarnings("unchecked")
    private String dump(final Object o) {
        if (o == null) {
            return "Can not dump null object.";
        }
        StringWriter sw = new StringWriter();
        String eol = Strings.getEol();
        if (o instanceof Object[]) {
            for (Object s : (Object[]) o) {
                sw.append(dump(s));
            }
        } else if (o instanceof Map) {
            Map<Object, Object> m = (Map<Object, Object>) o;
            for (Entry<Object, Object> entry : m.entrySet()) {
                sw.append(entry.getKey().toString());
                sw.append(eol);
                Object v = entry.getValue();
                if (v == null) {
                    sw.append("null");
                } else {
                    sw.append(v.toString());
                }
                sw.append(eol);
                sw.append(eol);
            }
        } else if (o instanceof Collection) {
            for (Object e : (Collection<?>) o) {
                sw.append(dump(e));
            }
        } else {
            sw.append(o.toString());
            sw.append(eol);
        }
        return sw.toString();
    }

    @Override
    public String toString() {
        if (dump == null) {
            dump = dump(obj);
        }
        return dump;
    }

    /**
     * Object.
     */
    private final Object obj;

    /**
     * Dump.
     */
    private String dump;
}
